#ifndef __PATH_FINDING_H__
#define __PATH_FINDING_H__

#include <vector>
#include <queue>
#include <cstdint>
#include <string>

#include <nan.h>

using namespace std;

struct Pos
{
    int x_;
    int y_;

    Pos() : x_(-1), y_(-1) {}
    Pos(int x, int y) : x_(x), y_(y) {}
};

struct Pre
{
    int x_;
    int y_;
    int cost_;
    Pre() : x_(-1), y_(-1), cost_(INT32_MAX) {}
};

struct DirectWeigh
{
    int x_;
    int y_;
    int weigh_;

    DirectWeigh(int x, int y, int weigh)
        : x_(x), y_(y), weigh_(weigh){};
};

struct State
{
    int x_;
    int y_;
    int cost_;  //从起点的消耗值
    int weigh_; // cost_ + 到终点预估值
    int directX_;
    int directY_;
    bool operator<(const State &s) const
    {
        return this->weigh_ > s.weigh_;
    }
};

struct PathFinding : public Nan::ObjectWrap
{
    vector<vector<int>> mapInfo_;
    inline int mapLength() { return mapInfo_.size(); }
    inline int mapWidth() { return mapInfo_.size() ? mapInfo_[0].size() : 0; }
    inline void initMapByLengthAndWidth(int mapLength, int mapWidth);
    inline void setMapBlock(int x, int y, int blockType);
    void initMapByFile(const string &fileName);

    inline bool walkAble(int x, int y);
    inline bool sideCheck(int x, int y);
    inline static int evaluateCost(Pos s, Pos e);

    void astar(Pos start, Pos end, vector<Pos> &result);

    bool forceNeighbor(State start, Pos end, Pos direct, priority_queue<State> &openList, vector<vector<Pre>> &pres);
    bool jumpPoint(State start, Pos end, Pos direct, priority_queue<State> &openList, vector<vector<Pre>> &pres);
    void jps(Pos start, Pos end, vector<Pos> &result);

    static NAN_MODULE_INIT(Init);
    static NAN_METHOD(New);
    static Nan::Persistent<v8::Function> constructor;

    static NAN_METHOD(MAPLENGTH);
    static NAN_METHOD(MAPWIDTH);
    static NAN_METHOD(INITMAPBYLENGTHANDWIDTH);
    static NAN_METHOD(SETMAPBLOCK);
    static NAN_METHOD(INITMAPBYFILE);
    static NAN_METHOD(ASTAR);
    static NAN_METHOD(JPS);
};

#endif